let utils = data["utils"];
let STUtil = data["STUtil"];
let Node = data["Node"];
let SplayTree = data["SplayTree"];
let isInBbox = data["isInBbox"];
let getBboxOverlap = data["getBboxOverlap"];
let cmp = data["cmp"];

console.log("07PolygonClipping_vector");

const crossProduct = (a, b) => a.x * b.y - a.y * b.x,
  dotProduct = (a, b) => a.x * b.x + a.y * b.y,
  compareVectorAngles = (basePt, endPt1, endPt2) => {
    const v1 = {
      x: endPt1.x - basePt.x,
      y: endPt1.y - basePt.y
    },
      v2 = {
        x: endPt2.x - basePt.x,
        y: endPt2.y - basePt.y
      },
      kross = crossProduct(v1, v2);
    return cmp(kross, 0)
  },
  length = v => Math.sqrt(dotProduct(v, v)),
  sineOfAngle = (pShared, pBase, pAngle) => {
    const vBase = {
      x: pBase.x - pShared.x,
      y: pBase.y - pShared.y
    },
      vAngle = {
        x: pAngle.x - pShared.x,
        y: pAngle.y - pShared.y
      };
    return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase)
  },
  cosineOfAngle = (pShared, pBase, pAngle) => {
    const vBase = {
      x: pBase.x - pShared.x,
      y: pBase.y - pShared.y
    },
      vAngle = {
        x: pAngle.x - pShared.x,
        y: pAngle.y - pShared.y
      };
    return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase)
  },
  closestPoint = (ptA1, ptA2, ptB) => {
    if (ptA1.x === ptA2.x) return {
      x: ptA1.x,
      y: ptB.y
    };
    if (ptA1.y === ptA2.y) return {
      x: ptB.x,
      y: ptA1.y
    };
    const v1 = {
      x: ptB.x - ptA1.x,
      y: ptB.y - ptA1.y
    },
      v2 = {
        x: ptB.x - ptA2.x,
        y: ptB.y - ptA2.y
      };
    let vFar, vA, farPt;
    dotProduct(v1, v1) > dotProduct(v2, v2) ? (vFar = v1, vA = {
      x: ptA2.x - ptA1.x,
      y: ptA2.y - ptA1.y
    }, farPt = ptA1) : (vFar = v2, vA = {
      x: ptA1.x - ptA2.x,
      y: ptA1.y - ptA2.y
    }, farPt = ptA2);
    const xDist = (ptB.x - farPt.x) / vA.x;
    if (ptB.y === farPt.y + xDist * vA.y) return ptB;
    const yDist = (ptB.y - farPt.y) / vA.y;
    if (ptB.x === farPt.x + yDist * vA.x) return ptB;
    const dist = dotProduct(vA, vFar) / dotProduct(vA, vA);
    return {
      x: farPt.x + dist * vA.x,
      y: farPt.y + dist * vA.y
    }
  },
  horizontalIntersection = (pt, v, y) => 0 === v.y ? null : {
    x: pt.x + v.x / v.y * (y - pt.y),
    y: y
  },
  verticalIntersection = (pt, v, x) => 0 === v.x ? null : {
    x: x,
    y: pt.y + v.y / v.x * (x - pt.x)
  },
  intersection = (pt1, v1, pt2, v2) => {
    if (0 === v1.x) return verticalIntersection(pt2, v2, pt1.x);
    if (0 === v2.x) return verticalIntersection(pt1, v1, pt2.x);
    if (0 === v1.y) return horizontalIntersection(pt2, v2, pt1.y);
    if (0 === v2.y) return horizontalIntersection(pt1, v1, pt2.y);
    const kross = crossProduct(v1, v2);
    if (0 == kross) return null;
    const ve = {
      x: pt2.x - pt1.x,
      y: pt2.y - pt1.y
    },
      d1 = crossProduct(ve, v1) / kross,
      d2 = crossProduct(ve, v2) / kross,
      x1 = pt1.x + d2 * v1.x,
      x2 = pt2.x + d1 * v2.x,
      y1 = pt1.y + d2 * v1.y,
      y2 = pt2.y + d1 * v2.y,
      x = (x1 + x2) / 2,
      y = (y1 + y2) / 2;
    return {
      x: x,
      y: y
    }
  },
  perpendicular = v => ({
    x: -v.y,
    y: v.x
  });


return {
  "utils": utils,
  "STUtil": STUtil,
  "Node": Node,
  "SplayTree": SplayTree,
  "isInBbox": isInBbox,
  "getBboxOverlap": getBboxOverlap,
  "cmp": cmp,
  "crossProduct": crossProduct,
  "dotProduct": dotProduct,
  "compareVectorAngles": compareVectorAngles,
  // "length":length,
  "sineOfAngle": sineOfAngle,
  "cosineOfAngle": cosineOfAngle,
  "closestPoint": closestPoint,
  "horizontalIntersection": horizontalIntersection,
  "verticalIntersection": verticalIntersection,
  "intersection": intersection,
  "perpendicular": perpendicular
}